<?php
/**
    This file is intended to be called via AJAX and passed
    a JSON-format object via a $_REQUEST variable whos
    name is defined in the constant string
    JSONMessageDispatcher::RequestKey.

    The $_REQUEST[JSONMessageDispatcher::RequestKey] object
    is assumed to be structured as specified by the JSONMessage
    interface specifies.

    It outputs JSON code in the JSONMessage-specified
    response structure.
*/
ob_start('ob_gzhandler');
session_cache_limiter('nocache');
session_start(); // MUST come after ob_gzhandler!

// Will point to a JSONResponse_Error obj if we hit a pre-dispatching error.
$PRE_DISPATCH_EXCEPTION = false;
do
{
    ob_start();
    try
    {
        $d = dirname(__FILE__);
        require_once( $d.'/JSONMessage.inc.php' );
        $custom = $d.'/JSONRequest-dispatch.config.php';
        if( @file_exists( $custom ) )
        {
            require_once( $custom );
        }
    }
    catch( Exception $e )
    {
        $PRE_DISPATCH_EXCEPTION = new JSONResponse_Error( null, $e );
        $PRE_DISPATCH_EXCEPTION->setErrorType(-1);
    }
    ob_end_clean();
} while(false);

function dispatch_JSONRequest()
{
    $res = null;
    $req = null;
    try
    {
        $ex = null;
        do
        {
            $req = JSONMessageDispatcher::getRequestFromEnv();
            if( ! $req )
            {
                $ex = new Exception("No JSONMessage request data found!",-1);
                break;
            }
            if( 0 == JSONRequestAuth::authorize( $req ) )
            { // note: we allow <0 ("unknown") to pass through!
                $ex = new Exception("Authentication rules denied access to the '".
                                    $req->getType()."' request.",-2);
                break;
            }
            $rd = JSONMessageDispatcher::getResponder( $req );
            if( ! $rd )
            {
                $ex = new Exception("No JSONResponse found for JSONMessage type '".$req->getType()."'!",-3);
                break;
            }
            $res = $rd->getResponse();// might throw
        } while(false);
        if( $ex )
        {
            $res = new JSONResponse_Error( $req, $ex );
            $res->setErrorType( $ex->getCode() );
        }
    }
    catch(Exception $e)
    { /**
            problem: we cannot differentiate between certain dispatching errors and
            message-level errors because getResponse() is both dispatching and
            instantiating (which may throw).
        */
        $rt = $res ? $res->getErrorType() : 1;
        $res = new JSONResponse_Error( $req, $e );
        $res->setErrorType( $rt );
        //$res->set('errorType',-1);
    }
    try
    {
        ob_start(); // in case the following throws...
        echo $res->toJSON();
        echo ob_get_clean();
    }
    catch(Exception $e)
    {
        $res = new JSONResponse_Error( $req, $e );
        $res->setErrorType(2);
        echo $res->toJSON();
    }
    echo "\n";
}
if( $PRE_DISPATCH_EXCEPTION )
{
    echo $PRE_DISPATCH_EXCEPTION->toJSON();
}
else
{
    dispatch_JSONRequest();
}
header('Content-Type: application/json');
header('Transfer-Size: '.ob_get_length() );
// Chrome complains about "unsafe" Content-Length and Connection headers, but removing them requires PHP 5.3+
//header_remove('Content-Length');
//header_remove('Connection');
//Even if i do this (which works, per the docs), PHP is setting them...
//header('Content-Length:');
//header('Connection:');
ob_end_flush();
?>
